using System;
using System.Collections.Generic;
using System.IO;
using System.Text;
using UMC.Data;
using UMC.WorkFlow.Subassembly;

namespace UMC.WorkFlow
{
    /// <summary>
    /// 活动图形结点
    /// </summary>
    public class Shape : IJSONType
    {
        /// <summary>
        /// 追加审批人
        /// </summary>
        /// <param name="task">作业</param>
        /// <param name="shape">节点</param>
        /// <param name="isHorizontal">是否水平追加</param>
        /// <param name="usernames">追加的用户</param>
        public static void AppendShape(UMC.WorkFlow.TaskInstance task, UMC.WorkFlow.Shape shape, bool isHorizontal, params string[] usernames)
        {
            var slst = new List<UMC.WorkFlow.Shape>();
            var llst = new List<UMC.WorkFlow.Line>();

            if (isHorizontal)
            {
                Line crLine = new Line();
                crLine.FromId = shape.Id;
                UMC.Data.Utility.Each<string>(usernames, name =>
                {
                    crLine.Id = String.Format("{0}c-c{1}", shape.Id, slst.Count);
                    var shp = new UMC.WorkFlow.Shape
                    {
                        Text = shape.Text
                    };
                    //shp.
                    UMC.WorkFlow.Identity identy = new UMC.WorkFlow.Identity
                    {
                        Username = name
                    };
                    shp.Identity = identy;
                    slst.Add(shp);
                    shp.Id = String.Format("{0}-{1}", shape.Id, slst.Count);
                    crLine.ToId = shp.Id;
                    llst.Add(crLine);

                    crLine.Status = UMC.WorkFlow.LineStatus.UnPass;
                    crLine = new Line
                    {
                        FromId = shp.Id
                    };
                });


                Utility.Each(task.Lines.FindAll(lne => lne.FromId == shape.Id), lne =>
                {
                    lne.FromId = slst[slst.Count - 1].Id;
                });
            }
            else
            {
                ///

                Utility.Each(usernames, name =>
                {
                    var shp = new UMC.WorkFlow.Shape();
                    UMC.WorkFlow.Identity identy = new UMC.WorkFlow.Identity();
                    identy.Username = name;
                    shp.Text = shape.Text;
                    shp.Status = UMC.WorkFlow.ShapeStatus.Activation;
                    shp.Identity = identy;
                    slst.Add(shp);
                    shp.Id = String.Format("{0}-{1}", shape.Id, slst.Count);
                });

                Utility.Each(task.Lines.FindAll(l => l.FromId == shape.Id), lne =>
                {
                    Utility.Each(slst, se =>
                    {
                        Line cline = new Line();
                        llst.Add(cline);
                        cline.FromId = se.Id;
                        cline.ToId = lne.ToId;
                        cline.Status = UMC.WorkFlow.LineStatus.UnPass;
                        cline.Id = String.Format("{0}-ln{1}", shape.Id, llst.Count);
                    });
                });
                Utility.Each(task.Lines.FindAll(l => l.ToId == shape.Id), lne =>
                {
                    Utility.Each(slst, se =>
                    {
                        Line cline = new Line();
                        llst.Add(cline);
                        cline.FromId = lne.FromId;
                        cline.ToId = se.Id;
                        cline.Status = UMC.WorkFlow.LineStatus.UnPass;
                        cline.Id = String.Format("{0}-ln{1}", shape.Id, llst.Count);
                    });
                });

            }
            task.Lines.AddRange(llst);
            task.Shapes.AddRange(slst);
        }

        /// <summary>
        /// 用户身份
        /// </summary>
        public UMC.WorkFlow.Identity Identity
        {
            get;
            set;
        }
        [Design(Caption = "标志")]
        public String Text { get; set; }
        public string Id { get; set; }
        /// <summary>
        /// 会签条件
        /// </summary>
        [Design(Caption = "激活脚本", Explain = "当脚本第一行第一列大于0，则会激活节点")]
        public SqlSetting ActivationSQL { get; set; }

        [Design(Caption = "激活百分比", Explain = "默认为100%，值1-100之间")]
        public int ActivationRate
        {
            get; set;
        }
        /// <summary>
        /// 处理流程呼叫的方法
        /// </summary>
        /// <param name="line">呼叫的线路</param>
        /// <param name="task">作业</param>
        public virtual void Activing(UMC.WorkFlow.Line line, TaskInstance task, TaskRuntime runtime)
        {
            if (task.Lines.Exists(lne => lne.Status == LineStatus.UnPass && lne.ToId == line.ToId && lne.IsMust))
            {
                return;
            }

            int count = task.Lines.FindAll(lne => lne.Status == LineStatus.Passed && lne.ToId == line.ToId).Count;

            if (this.ActivationRate > 0 && this.ActivationRate < 100)
            {
                var total = task.Lines.FindAll(lne => lne.ToId == line.ToId).Count + 0f;
                if ((count / total) >= this.ActivationRate / 100f)
                {
                    runtime.Progress(this.Id);
                    return;
                }
                else
                {
                    return;
                }

            }
            if (this.ActivationSQL != null)
            {
                System.Collections.Hashtable hash = new System.Collections.Hashtable(runtime.Items);

                hash["Shape.Id"] = this.Id;
                hash["Line.Id"] = line.Id;
                hash["Line.PassCount"] = count;
                object obj = UMC.WorkFlow.Subassembly.SubassemblyHelper.ExecuteScalar(ActivationSQL, hash);
                if (obj != null)
                {
                    if (Utility.IntParse(obj.ToString(), 0) > 0)
                    {
                        runtime.Progress(this.Id);
                    }
                }
            }
        }
        /// <summary>
        /// 线激活当前的结点
        /// </summary>
        /// <param name="line">线</param>
        /// <param name="task">作业事例</param>
        public virtual void Activation(Line line, TaskInstance task, TaskRuntime runtime)
        {

        }

        protected virtual string JSONName()
        {
            return this.GetType().Name;
        }
        public virtual Func<object> GetInstance(string prototypeName)
        {
            switch (prototypeName)
            {
                case "Identity":
                    return () => new Identity();
                default:
                    return () => String.Empty;
            }
            //throw new NotImplementedException();
        }

        public virtual void Read(string key, object value)
        {
            switch (key)
            {
                case "Identity":
                    this.Identity = (Identity)value;//Convert.ToBoolean(value);
                    break;
                case "Id":
                    this.Id = value as string;
                    break;
                case "Status":
                    this.Status = Utility.Parse(value as string, ShapeStatus.Undefine);
                    break;
                case "Text":
                    this.Text = value as string;
                    break;
                    //,LineStatus.UnPass);
            }
        }
        protected virtual void WriteProperty(TextWriter writer)
        {

            writer.Write(',');
            JSON.Serialize("Id", this.Id, writer);
            writer.Write(',');
            JSON.Serialize("Text", this.Text, writer);
            if (this.Identity != null)
            {
                writer.Write(',');
                JSON.Serialize("Identity", this.Identity, writer);
            }
            if (this.Status > ShapeStatus.Undefine)
            {
                writer.Write(',');
                JSON.Serialize("Status", this.Status, writer);
            }

        }

        public void Write(TextWriter writer)
        {
            writer.Write('{');
            JSON.Serialize(JSON.Constructor, writer);
            writer.Write(":");
            JSON.Serialize(JSONName(), writer);
            WriteProperty(writer);
            writer.Write('}');
        }
        /// <summary>
        /// 矢量的工作状态
        /// </summary>
        public ShapeStatus Status { get; set; }


    }
}
